package com.mikelouis.test.scala.proginscala.chapter10

/**
 * Created by yuazhu on 1/3/2015.
 */
object LayoutElement {
  def main(args: Array[String]) {
    // test ArrayElement
    val ae: Element = new ArrayElement(Array("Hello", "World"))
    println(ae.height + "," + ae.width)

    val e: Element = new ArrayElementParamField(Array("Hello, World"))
    println(e.height + "," + e.width)

    val line: Element = new LineElement("Dear World")
    println(line.height + "," + line.width)

    val e3 = new UniformElement('x', 2, 3)
    println(e3.height + ", " + e3.width)

    println("******************************************")
    ae.demo()
    line.demo()
    e3.demo()
  }
}

/**
 * abstract修饰符说明类或许有没实现的抽象成员
 *
 * 如果方法没有实现（也就是说，没有等号或方法体），它就是抽象的
 *
 * 另一个术语用法需要分辨声明：declaration和定义：definition。类Element声明了抽象方法contents，但当前没有定义具体方法
 */
abstract class Element {
  /**
   * 抽象方法
   * @return
   */
  def contents: Array[String]

  /**
   * height方法返回contents里的行数
   * @return
   */
  def height: Int = contents.length

  /**
   * width方法返回第一行的长度，或如果元素没有行记录，返回零
   *
   * 等价于: def width(): Int ...
   * @return
   */
  def width: Int = if (height == 0) 0 else contents(0).length

  /**
   * polymorphism test
   */
  def demo() = println("Element's implementation invoked")
}

class ArrayElement(conts: Array[String]) extends Element {
  /**
   * 抽象方法
   * @return
   */
  override def contents: Array[String] = conts

  override def demo() = println("ArrayElement's implementation invoked")
}

/**
 * 参数化字段：parametric field定义中组合参数和字段
 *
 * 等价于
 * class ArrayElement(x123: Array[String]) extends Element { val contents: Array[String] = x123 }
 *
 * 同样也可以使用var前缀类参数，这种情况下相应的字段将能重新被赋值
 * @param contents
 */
class ArrayElementParamField(val contents: Array[String]) extends Element {

}

class LineElement(s: String) extends ArrayElement(Array(s)) {
  /**
   * height方法返回contents里的行数
   * @return
   */
  override def height: Int = s.length

  /**
   * width方法返回第一行的长度，或如果元素没有行记录，返回零
   *
   * 等价于: def width(): Int ...
   * @return
   */
  override def width: Int = 1

  /**
   * 要确保成员不被子类重载
   */
  override final def demo() = println("LineElement's implementation invoked")
}

/**
 * 确保整个类都没有子类。要做到这点只要简单地通过在类的声明上添加final修饰符把整个类声明为final即可
 * @param ch
 * @param width
 * @param height
 */
final class UniformElement(ch: Char, override val width: Int, override val height: Int) extends Element {
  def contents = Array(ch.toString)
}
